hotpatch-for-apache-log4j を無効化する方法を検証してみた
はじめに
log4j2の脆弱性(CVE-2021-44228)の対策としてAWSからパッチがリリースされています。このパッチは起動中のJVMを検出してパッチ済みのクラスファイルを送り込むことで脆弱性を回避するものです。しかし起動しているJVMプロセスにクラスファイルのロードを行うのは避けたい場合もあると思います。今回はこのパッチを無効化する方法を検証してみました。
Amazon Linuxで提供されているJVMとパッチの関係
このパッチは現在 Amazon CorrettoおよびAmazon Linuxによって提供されるOpenJDKのセキュリティアップデートとしてJVMともにインストールされるため、新たにこれらのパッケージをインストールしたりインスタンス起動時のアップデートでパッチがインストールされます。各パッケージのアップデートの詳細は以下の参考リンクを参照してください。
参考: Amazon Linux Hotpatch Announcement for Apache Log4j
パッチを無効化する
パッチを無効化する方法はこのアナウンスで紹介されています。
If you need to disable the hotpatch, this can be done by running
sudo touch /etc/log4j-cve-2021-44228-hotpatch.kill
. This will create a file that the hotpatch service will detect and will not attempt to apply the hotpatch to any running JVM it finds.
Correttoインストール済みのAMI(作成方法は後述) からAutoScaling Groupなどでインスタンスを自動起動する場合にパッチの無効化を自動で行う方法をいくつか検証してみます。
結論から言うとインスタンス起動時にパッチを無効化するには後者のkill fileを含めておく方法だけが有効でした。
検証するパターン
- userdataでkill fileを作成
- AMIにkill fileを含めておく
userdataでkill fileを作成
以下のようなスクリプトをuserdataに設定します。
#!/bin/bash touch /etc/log4j-cve-2021-44228-hotpatch.kill
起動後にログを確認します。
ip-172-31-19-248
はAMI作成時のインスタンスのIPアドレス、ip-172-31-25-154
は検証用に起動したインスタンスのIPアドレスです。検証用のインスタンスでも起動時にパッチが動作していることがわかります。これはuserdataのスクリプトが実行されるよりも前にパッチ用のスクリプトが起動するためです。
sh-4.2$ sudo less /var/log/messages | grep log4j Dec 22 11:05:08 ip-172-31-19-248 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] Starting up now... Dec 22 11:05:08 ip-172-31-19-248 yum[3333]: Installed: log4j-cve-2021-44228-hotpatch-1.1-9.amzn2.noarch Dec 22 11:05:08 ip-172-31-19-248 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] No JVMs found, exiting gracefully Dec 22 11:08:36 ip-172-31-25-154 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] Starting up now... Dec 22 11:08:37 ip-172-31-25-154 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] No JVMs found, exiting gracefully
プロセスを確認してみるとパッチ用のスクリプトが起動しています。
sh-4.2$ ps axu | grep log4j root 2553 0.0 0.3 124204 3144 ? Ss 11:08 0:00 /bin/bash /usr/bin/log4j-cve-2021-44228-hotpatch -w 1800 -m 10 ssm-user 5943 0.0 0.0 119424 956 pts/0 S+ 11:15 0:00 grep log4j
AMI内にkill fileを作成しておく
同様にログを確認するとFound kill file, not applying patch.
というログが出力されてパッチの適用が行われていないことがわかります。
sh-4.2$ sudo less /var/log/messages | grep log4j Dec 22 11:11:28 ip-172-31-31-245 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] Starting up now... Dec 22 11:11:28 ip-172-31-31-245 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] No JVMs found, exiting gracefully Dec 22 11:11:28 ip-172-31-31-245 yum[3350]: Installed: log4j-cve-2021-44228-hotpatch-1.1-9.amzn2.noarch Dec 22 11:33:54 ip-172-31-28-170 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] Found kill file, not applying patch.
こちらでもスクリプトは起動しています。(kill fileがあるのにスクリプトが起動している理由は本稿の後半「参考情報」を参照)
sh-4.2$ ps axu | grep log4j root 2563 0.0 0.3 124204 3160 ? Ss 11:33 0:00 /bin/bash /usr/bin/log4j-cve-2021-44228-hotpatch -w 1800 -m 10 ssm-user 10679 0.0 0.0 119424 940 pts/0 S+ 11:54 0:00 grep log4j
このパターンで使ったpackerでのプロビジョニングスクリプトは以下になります。packerの設定ファイルは参考情報の「Correttoを含むAMIを作成する」に掲載しています。
#!/bin/bash sudo yum install -y java-11-amazon-corretto-headless sudo touch /etc/log4j-cve-2021-44228-hotpatch.kill
まとめ
取り急ぎですが、パッチを自動で無効化する方法を検証してみました。
参考情報
Correttoを含むAMIを作成する
packerでCorrettoを含むAMIを作成します。使用するスクリプトは下記の通りです。
packer JSON
{ "builders": [ { "type": "amazon-ebs", "region": "ap-northeast-1", "source_ami": "ami-0218d08a1f9dac831", "ami_name": "AL2 with coretto with log4jpatch", "instance_type": "t2.small", "ssh_username": "ec2-user", "ssh_timeout": "5m", "ssh_pty": true } ], "provisioners": [ { "type": "shell", "scripts": [ "scripts/install_java.sh" ] } ] }
scripts/install_java.sh
#!/bin/bash sudo yum install -y java-11-amazon-corretto-headless
記事執筆時点(2021/12/22) でインストールされるパッケージの情報は下記の通りです。このバージョンではパッチが一緒にインストールされます。
sh-4.2$ sudo yum info java-11-amazon-corretto-headless Loaded plugins: extras_suggestions, langpacks, priorities, update-motd Installed Packages Name : java-11-amazon-corretto-headless Arch : x86_64 Epoch : 1 Version : 11.0.13+8 Release : 2.amzn2 Size : 304 M Repo : installed From repo : amzn2-core Summary : Amazon Corretto headless development environment URL : https://github.com/corretto/corretto-11 License : ASL 1.1 and ASL 2.0 and BSD and BSD with advertising and GPL+ and GPLv2 and GPLv2 with exceptions and IJG and LGPLv2+ and MIT and MPLv2.0 and : Public Domain and W3C and zlib and ISC and FTL and RSA. Description : Amazon Corretto's packaging of the runtime core elements of the : OpenJDK 11 code. (Headless environment)
パッチ用スクリプトが常に起動している理由
パッチ用の起動スクリプトはサービスとして起動してパッチを適用した後一定時間スリープして終了し、systemdによって再度起動されます。そのためパッチを行っていない時でもスクリプトが動作しています。このスクリプトやサービスの設定定義は以下で参照できます。
rpm -ql log4j-cve-2021-44228-hotpatch /usr/bin/log4j-cve-2021-44228-hotpatch /usr/lib/systemd/system/log4j-cve-2021-44228-hotpatch.service /usr/share/log4j-cve-2021-44228-hotpatch/jdk11/Log4jHotPatch.jar /usr/share/log4j-cve-2021-44228-hotpatch/jdk17/Log4jHotPatchFat.jar /usr/share/log4j-cve-2021-44228-hotpatch/jdk8/Log4jHotPatch.jar